const fs = require('fs');
const path = require('path');
const sharp = require('sharp');
const readline = require('readline');

/**
 * 图片自动缩小工具（增强版）
 * 说明:
    1. 设置保底百分比缩小值为20
    2. 缩小后还大于512的长边再进行缩小到512的比例
    3. 分包处理，处理已导出的组件内的 大图片、loader引用组件大图片、列表引用组件大图片
    4. 输出更换日志，包括尺寸、大小、路径
    5. 找出所有的后，需要一个确定执行的操作
 */ 

class USSImageResizerEnhanced {
    constructor(targetPackage = null) {
        this.fguiProjectPath = "G:\\uss\\uss-art\\svn\\hegui2\\fgui";
        this.assetsPath = path.join(this.fguiProjectPath, 'assets');
        this.targetPackage = targetPackage; // 指定要处理的包，null表示处理所有包
        this.minShrinkPercentage = 20; // 保底缩小百分比
        this.maxDimension = 512; // 最大边长
        this.imagesToResize = []; // 需要缩小的图片列表
        this.resizedImages = []; // 已缩小的图片记录
        this.backupDir = path.join(__dirname, 'image_backups');
        
        // 从检查工具复用的数据结构
        this.packageResources = new Map();
        this.exportedResources = new Map();
        this.packageIds = new Map(); // 存储包ID映射
        
        // 创建日志和备份目录
        this.logsDir = path.join(__dirname, 'logs');
        if (!fs.existsSync(this.logsDir)) {
            fs.mkdirSync(this.logsDir, { recursive: true });
        }
        if (!fs.existsSync(this.backupDir)) {
            fs.mkdirSync(this.backupDir, { recursive: true });
        }
        
        // 生成日志文件名 - 使用当前时区时间
        const now = new Date();
        const timezoneOffset = now.getTimezoneOffset();
        const localTime = new Date(now.getTime() - (timezoneOffset * 60 * 1000));
        const timestamp = localTime.toISOString()
            .replace(/[:.]/g, '-')
            .replace('T', '_')
            .slice(0, -5);
        
        this.logFile = path.join(this.logsDir, `uss-image-resizer-${timestamp}.log`);
        
        console.log('🖼️  USS FGUI 图片自动缩小工具 (增强版)');
        console.log('====================================\n');
        if (this.targetPackage) {
            console.log(`🎯 目标包: ${this.targetPackage}`);
        } else {
            console.log(`🎯 目标包: 所有包`);
        }
        console.log(`📁 日志文件: ${this.logFile}`);
        console.log(`📁 备份目录: ${this.backupDir}`);
        console.log(`⚙️  配置: 保底缩小 ${this.minShrinkPercentage}%, 最大边长 ${this.maxDimension}px`);
        console.log(`💡 特性: 保持FGUI界面尺寸不变，调整原大小和填充属性\n`);
    }

    // 日志记录
    log(message, type = 'info') {
        const timestamp = new Date().toLocaleString();
        const logMessage = `${message}`;
        
        if (type === 'error') {
            console.error('❌ ' + message);
        } else if (type === 'warning') {
            console.log('⚠️  ' + message);
        } else if (type === 'success') {
            console.log('✅ ' + message);
        } else if (type === 'detail') {
            console.log('📋 ' + message);
        } else {
            console.log('🔍 ' + message);
        }
        
        fs.appendFileSync(this.logFile, logMessage + '\n', 'utf8');
    }

    // 从检查工具复用的方法 - 获取所有包
    getPackages() {
        if (!fs.existsSync(this.assetsPath)) return [];
        try {
            const items = fs.readdirSync(this.assetsPath);
            const packages = items.filter(item => {
                const itemPath = path.join(this.assetsPath, item);
                return fs.statSync(itemPath).isDirectory();
            });
            
            // 如果指定了目标包，只返回该包
            if (this.targetPackage) {
                if (packages.includes(this.targetPackage)) {
                    return [this.targetPackage];
                } else {
                    this.log(`错误: 指定的包 "${this.targetPackage}" 不存在`, 'error');
                    return [];
                }
            }
            
            return packages;
        } catch (error) {
            return [];
        }
    }

    // 显示包选择菜单
    async showPackageSelection() {
        const packages = this.getPackages();
        
        if (packages.length === 0) {
            this.log('未找到任何包', 'error');
            return null;
        }

        console.log('\n' + '='.repeat(50));
        console.log('📦 请选择要处理的包');
        console.log('='.repeat(50));
        console.log('  0. 所有包');
        packages.forEach((pkg, index) => {
            console.log(`  ${index + 1}. ${pkg}`);
        });
        console.log('='.repeat(50));

        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });

        return new Promise((resolve) => {
            rl.question(`\n请选择包 (0-${packages.length}): `, (answer) => {
                rl.close();
                const choice = parseInt(answer);
                
                if (isNaN(choice) || choice < 0 || choice > packages.length) {
                    console.log('❌ 无效选择，请输入有效数字');
                    resolve(null);
                } else if (choice === 0) {
                    resolve(null); // 所有包
                } else {
                    resolve(packages[choice - 1]);
                }
            });
        });
    }

    // 从检查工具复用的方法 - 分析包资源ID映射
    analyzePackageResourceIds(pkg) {
        const pkgPath = path.join(this.assetsPath, pkg);
        const xmlFiles = this.findFilesDeep(pkgPath, '.xml');
        
        const resources = [];
        
        xmlFiles.forEach(xmlFile => {
            try {
                const content = fs.readFileSync(xmlFile, 'utf8');
                
                // 查找所有资源的ID映射
                const resourceItems = this.findResourceIds(content);
                resourceItems.forEach(item => {
                    resources.push({
                        type: item.type,
                        name: item.name,
                        id: item.id,
                        file: path.relative(pkgPath, xmlFile),
                        package: pkg
                    });
                });
                
            } catch (error) {
                this.log(`无法分析资源ID: ${pkg}/${path.basename(xmlFile)}`, 'warning');
            }
        });

        this.packageResources.set(pkg, resources);
        
        // 分析package.xml获取包ID
        this.analyzePackageId(pkg);
    }

    // 分析包ID
    analyzePackageId(pkg) {
        const pkgPath = path.join(this.assetsPath, pkg);
        const packageXMLPath = path.join(pkgPath, 'package.xml');
        
        if (!fs.existsSync(packageXMLPath)) {
            this.log(`包 "${pkg}" 没有 package.xml 文件`, 'warning');
            return;
        }
        
        try {
            const content = fs.readFileSync(packageXMLPath, 'utf8');
            const packageIdMatch = content.match(/<packageDescription[^>]*id="([^"]*)"/);
            if (packageIdMatch) {
                const packageId = packageIdMatch[1];
                this.packageIds.set(pkg, packageId);
                this.log(`包 "${pkg}" 的ID为: ${packageId}`, 'detail');
            } else {
                this.log(`包 "${pkg}" 的package.xml中没有找到packageDescription id`, 'warning');
            }
        } catch (error) {
            this.log(`读取package.xml失败: ${pkg} - ${error.message}`, 'warning');
        }
    }

    // 从检查工具复用的方法 - 查找资源ID
    findResourceIds(xmlContent) {
        const resourceItems = [];
        
        // 查找所有组件 (component)
        const componentRegex = /<component[^>]*id="([^"]*)"[^>]*name="([^"]*)"[^>]*>/gi;
        let match;
        while ((match = componentRegex.exec(xmlContent)) !== null) {
            resourceItems.push({
                type: 'component',
                id: match[1],
                name: match[2]
            });
        }
        
        // 查找所有图片资源 (image)
        const imageRegex = /<image[^>]*id="([^"]*)"[^>]*name="([^"]*)"[^>]*>/gi;
        while ((match = imageRegex.exec(xmlContent)) !== null) {
            resourceItems.push({
                type: 'resource',
                id: match[1],
                name: match[2]
            });
        }
        
        return resourceItems;
    }

    // 从检查工具复用的方法 - 查找导出的组件
    findExportedComponentsInPackageXML(packageContent) {
        const exportedComponents = [];
        
        const componentRegex = /<component\s+[^>]*?id="([^"]+)"[^>]*?exported="true"[^>]*?>/gi;
        let match;
        
        while ((match = componentRegex.exec(packageContent)) !== null) {
            const componentId = match[1];
            const fullTag = match[0];
            
            const exportedMatch = /exported\s*=\s*"true"/i.exec(fullTag);
            if (exportedMatch) {
                exportedComponents.push(componentId);
            }
        }
        
        return exportedComponents;
    }

    // 从检查工具复用的方法 - 根据组件ID查找组件文件
    findComponentFileById(pkgPath, componentId) {
        const xmlFiles = this.findFilesDeep(pkgPath, '.xml');
        
        for (const xmlFile of xmlFiles) {
            try {
                const content = fs.readFileSync(xmlFile, 'utf8');
                const componentRegex = new RegExp(`<component[^>]*id="${componentId}"[^>]*>`, 'i');
                if (componentRegex.test(content)) {
                    return xmlFile;
                }
            } catch (error) {
                this.log(`读取组件文件失败: ${xmlFile}`, 'warning');
            }
        }
        
        return null;
    }

    // 从检查工具复用的方法 - 在递归开始时验证组件导出状态
    findImagesInExportedComponent(componentFile, pkgPath, foundImages, processedComponents, callPath, depth = 0) {
        if (depth > 10) return;
        
        try {
            const content = fs.readFileSync(componentFile, 'utf8');
            const baseDir = path.dirname(componentFile);
            const relativePath = path.relative(pkgPath, componentFile);
            
            // 验证当前组件是否确实导出（深度防御）
            if (depth === 0) {
                const componentId = this.extractComponentIdFromFile(content);
                if (componentId && !this.isComponentExported(pkgPath, componentId)) {
                    return;
                }
            }
            
            // 原有逻辑...
            this.findDirectImagesInComponent(content, pkgPath, foundImages, baseDir, callPath, depth, processedComponents);
            this.findLoaderImagesInComponent(content, pkgPath, foundImages, baseDir, callPath);
            this.findSubComponentsInComponent(content, pkgPath, foundImages, processedComponents, baseDir, depth, callPath);
            
        } catch (error) {
            this.log(`无法读取组件文件: ${componentFile} - ${error.message}`, 'error');
        }
    }

    // 从检查工具复用的方法 - 从组件文件内容中提取组件ID
    extractComponentIdFromFile(xmlContent) {
        const componentRegex = /<component[^>]*id="([^"]*)"[^>]*>/i;
        const match = componentRegex.exec(xmlContent);
        return match ? match[1] : null;
    }

    // 从检查工具复用的方法 - 验证组件是否导出
    isComponentExported(pkgPath, componentId) {
        const packageXMLPath = path.join(pkgPath, 'package.xml');
        if (!fs.existsSync(packageXMLPath)) {
            return false;
        }
        
        try {
            const content = fs.readFileSync(packageXMLPath, 'utf8');
            const exportedRegex = new RegExp(`<component[^>]*id="${componentId}"[^>]*exported="true"[^>]*>`, 'i');
            return exportedRegex.test(content);
        } catch (error) {
            this.log(`检查组件导出状态失败: ${componentId} - ${error.message}`, 'warning');
            return false;
        }
    }

    // 从检查工具复用的方法 - 查找组件中直接引用的图片
    findDirectImagesInComponent(xmlContent, pkgPath, foundImages, baseDir, callPath, depth = 0, processedComponents = new Set()) {
        // 查找image标签 - 同时处理fileName和src属性
        const imageRegex = /<image[^>]*?(?:fileName="([^"]*)"|src="([^"]*)")[^>]*>/gi;
        let match;
        
        while ((match = imageRegex.exec(xmlContent)) !== null) {
            const fileName = match[1];
            const srcId = match[2];
            
            // 优先处理src属性（资源ID引用）
            if (srcId) {
                // 通过资源ID查找对应的图片文件
                const imageFileFromSrc = this.findImageFileByResourceId(pkgPath, srcId);
                if (imageFileFromSrc) {
                    this.checkAndAddImage(imageFileFromSrc, pkgPath, foundImages, baseDir, callPath);
                    continue;
                }
            }
            
            // 处理fileName属性
            if (fileName) {
                this.checkAndAddImage(fileName, pkgPath, foundImages, baseDir, callPath);
            }
        }
        
        // 查找list标签的defaultItem属性
        const listRegex = /<list[^>]*defaultItem="([^"]*)"[^>]*>/gi;
        while ((match = listRegex.exec(xmlContent)) !== null) {
            const defaultItem = match[1];
            
            if (defaultItem.startsWith('ui://')) {
                // 解析ui://格式的defaultItem
                const componentPath = this.resolveUIPath(defaultItem, pkgPath);
                if (componentPath && componentPath.endsWith('.xml')) {
                    // 递归分析组件文件中的图片，传递深度和已处理集合
                    this.analyzeComponentImages(componentPath, pkgPath, foundImages, callPath, depth + 1, processedComponents);
                }
            }
        }
        
        // 同时查找其他可能的图片引用格式
        const otherImageRefs = this.extractOtherImageReferences(xmlContent);
        otherImageRefs.forEach(fileName => {
            this.checkAndAddImage(fileName, pkgPath, foundImages, baseDir, callPath);
        });
    }

    // 添加方法：分析组件文件中的图片
    analyzeComponentImages(componentFile, pkgPath, foundImages, callPath, depth = 0, processedComponents = new Set()) {
        // 检查递归深度，防止无限递归
        if (depth > 5) {
            this.log(`递归深度达到限制，停止分析: ${componentFile}`, 'warning');
            return;
        }
        
        // 检查是否已经处理过这个组件
        if (processedComponents.has(componentFile)) {
            return;
        }
        
        // 添加到已处理集合
        processedComponents.add(componentFile);
        
        if (!fs.existsSync(componentFile)) {
            return;
        }
        
        // 检查文件扩展名，只处理XML文件
        if (path.extname(componentFile).toLowerCase() !== '.xml') {
            return;
        }
        
        // 检查是否是package.xml，避免递归分析包文件
        if (path.basename(componentFile) === 'package.xml') {
            return;
        }
        
        try {
            const content = fs.readFileSync(componentFile, 'utf8');
            const baseDir = path.dirname(componentFile);
            const relativePath = path.relative(this.assetsPath, componentFile);
            
            // 记录调用路径
            const newCallPath = [...callPath, relativePath];
            
            // 查找组件中的图片引用
            this.findDirectImagesInComponent(content, pkgPath, foundImages, baseDir, newCallPath, depth + 1, processedComponents);
            this.findLoaderImagesInComponent(content, pkgPath, foundImages, baseDir, newCallPath);
            
            // 递归查找子组件，传递深度和已处理集合
            this.findSubComponentsInComponent(content, pkgPath, foundImages, processedComponents, baseDir, depth + 1, newCallPath);
            
        } catch (error) {
            this.log(`分析组件图片失败: ${componentFile} - ${error.message}`, 'warning');
        }
    }

    // 从检查工具复用的方法 - 通过资源ID查找图片文件
    findImageFileByResourceId(pkgPath, resourceId) {
        const pkgName = path.basename(pkgPath);
        const resources = this.packageResources.get(pkgName) || [];
        
        // 查找匹配的资源
        const resource = resources.find(r => r.id === resourceId);
        if (resource && resource.type === 'resource') {
            // 首先尝试从package.xml获取精确路径
            const imagePath = this.findImagePathInPackageXML(pkgPath, resourceId);
            if (imagePath) {
                return imagePath;
            }
            
            // 如果无法从package.xml获取，尝试各种可能的路径
            const possiblePaths = [
                path.join(pkgPath, 'image', resource.name),
                path.join(pkgPath, resource.name),
                path.join(pkgPath, 'image', resource.name + '.png'),
                path.join(pkgPath, 'image', resource.name + '.jpg'),
                path.join(pkgPath, 'image', resource.name + '.jpeg'),
                path.join(pkgPath, resource.name + '.png'),
                path.join(pkgPath, resource.name + '.jpg'),
                path.join(pkgPath, resource.name + '.jpeg')
            ];
            
            for (const possiblePath of possiblePaths) {
                if (fs.existsSync(possiblePath)) {
                    return possiblePath;
                }
            }
            
            // 如果还找不到，在整个包内搜索文件名
            const allImages = this.findFilesDeep(pkgPath, ['.png', '.jpg', '.jpeg']);
            for (const imageFile of allImages) {
                const fileName = path.basename(imageFile, path.extname(imageFile));
                if (fileName === resource.name) {
                    return imageFile;
                }
            }
        }
        
        return null;
    }

    // 从检查工具复用的方法 - 从package.xml中查找资源路径
    findImagePathInPackageXML(pkgPath, resourceId) {
        const packageXMLPath = path.join(pkgPath, 'package.xml');
        if (!fs.existsSync(packageXMLPath)) {
            return null;
        }
        
        try {
            const content = fs.readFileSync(packageXMLPath, 'utf8');
            const resourceRegex = new RegExp(`<image[^>]*id="${resourceId}"[^>]*>`, 'i');
            const match = resourceRegex.exec(content);
            
            if (match) {
                const nameMatch = /name="([^"]*)"/i.exec(match[0]);
                const pathMatch = /path="([^"]*)"/i.exec(match[0]);
                
                if (nameMatch) {
                    const name = nameMatch[1];
                    let resourcePath = pathMatch ? pathMatch[1] : '';
                    
                    if (resourcePath.startsWith('/')) {
                        resourcePath = resourcePath.substring(1);
                    }
                    if (resourcePath.endsWith('/')) {
                        resourcePath = resourcePath.substring(0, resourcePath.length - 1);
                    }
                    
                    let fullPath;
                    if (resourcePath) {
                        fullPath = path.join(pkgPath, resourcePath, name);
                    } else {
                        fullPath = path.join(pkgPath, name);
                    }
                    
                    if (fs.existsSync(fullPath)) {
                        return fullPath;
                    }
                    
                    // 尝试添加扩展名
                    if (!fullPath.toLowerCase().endsWith('.png') && 
                        !fullPath.toLowerCase().endsWith('.jpg') && 
                        !fullPath.toLowerCase().endsWith('.jpeg')) {
                        
                        const extensions = ['.png', '.jpg', '.jpeg'];
                        for (const ext of extensions) {
                            const pathWithExt = fullPath + ext;
                            if (fs.existsSync(pathWithExt)) {
                                return pathWithExt;
                            }
                        }
                    }
                }
            }
        } catch (error) {
            this.log(`读取package.xml失败: ${error.message}`, 'warning');
        }
        
        return null;
    }

    // 从检查工具复用的方法 - 提取其他图片引用
    extractOtherImageReferences(xmlContent) {
        const refs = [];
        
        const patterns = [
            /url="([^"]*\.(png|jpg|jpeg))"/gi,
            /file="([^"]*\.(png|jpg|jpeg))"/gi,
            /texture="([^"]*\.(png|jpg|jpeg))"/gi
        ];
        
        patterns.forEach(pattern => {
            let match;
            while ((match = pattern.exec(xmlContent)) !== null) {
                refs.push(match[1]);
            }
        });
        
        return refs;
    }

    // 从检查工具复用的方法 - 查找loader引用的图片
    findLoaderImagesInComponent(xmlContent, pkgPath, foundImages, baseDir, callPath) {
        const loaderRegex = /<loader(?!.*clearOnPublish[^>]*)[^>]*url="([^"]*)"[^>]*>/gi;
        let match;
        
        while ((match = loaderRegex.exec(xmlContent)) !== null) {
            const url = match[1];
            
            if (url.startsWith('ui://')) {
                // 解析ui://格式的URL
                const imagePath = this.resolveUIPath(url, pkgPath);
                if (imagePath) {
                    this.checkAndAddImage(imagePath, pkgPath, foundImages, path.dirname(imagePath), callPath);
                }
            } else {
                this.checkAndAddImage(url, pkgPath, foundImages, baseDir, callPath);
            }
        }
    }

    // 解析ui://格式的URL
    resolveUIPath(uiUrl, basePkgPath) {
        // ui://d1mbpdanf1251 格式
        // 去掉ui://前缀
        const resourceRef = uiUrl.substring(5);
        
        // 在所有包中查找匹配的资源
        const packages = this.getPackages();
        
        for (const pkg of packages) {
            const pkgPath = path.join(this.assetsPath, pkg);
            const packageId = this.packageIds.get(pkg);
            
            if (packageId && resourceRef.startsWith(packageId)) {
                // 提取资源ID
                const resourceId = resourceRef.substring(packageId.length);
                
                // 首先尝试查找组件文件
                const componentFile = this.findComponentFileById(pkgPath, resourceId);
                if (componentFile) {
                    return componentFile;
                }
                
                // 如果没有找到组件，尝试查找图片文件
                const imagePath = this.findImageFileByResourceId(pkgPath, resourceId);
                if (imagePath) {
                    return imagePath;
                }
            }
        }
        
        return null;
    }

    // 从检查工具复用的方法 - 查找子组件
    findSubComponentsInComponent(xmlContent, pkgPath, foundImages, processedComponents, baseDir, depth, callPath) {
        const componentRefs = this.extractComponentReferences(xmlContent);
        
        componentRefs.forEach(ref => {
            let subComponentFile = null;
            
            if (ref.type === 'src') {
                subComponentFile = this.findComponentFileById(pkgPath, ref.value);
            } else if (ref.type === 'name') {
                subComponentFile = this.findComponentFileByName(pkgPath, ref.value, baseDir);
            }
            
            if (subComponentFile && !processedComponents.has(subComponentFile)) {
                processedComponents.add(subComponentFile);
                const newCallPath = [...callPath, path.relative(pkgPath, subComponentFile)];
                this.findImagesInExportedComponent(subComponentFile, pkgPath, foundImages, processedComponents, newCallPath, depth + 1);
            }
        });
    }

    // 从检查工具复用的方法 - 提取组件引用
    extractComponentReferences(xmlContent) {
        const refs = [];
        
        const srcRegex = /<component[^>]*src="([^"]*)"[^>]*>/gi;
        let match;
        while ((match = srcRegex.exec(xmlContent)) !== null) {
            refs.push({
                type: 'src',
                value: match[1]
            });
        }
        
        const componentRefRegex = /<component[^>]*name="([^"]*\.xml)"[^>]*>/gi;
        while ((match = componentRefRegex.exec(xmlContent)) !== null) {
            refs.push({
                type: 'name',
                value: match[1]
            });
        }
        
        return refs;
    }

    // 从检查工具复用的方法 - 根据组件名称查找组件文件
    findComponentFileByName(pkgPath, componentName, baseDir) {
        let componentFile = path.join(baseDir, componentName);
        if (fs.existsSync(componentFile)) {
            return componentFile;
        }
        
        const xmlFiles = this.findFilesDeep(pkgPath, '.xml');
        for (const xmlFile of xmlFiles) {
            const fileName = path.basename(xmlFile);
            if (fileName === componentName) {
                return xmlFile;
            }
        }
        
        return null;
    }

    // 修改后的检查图片方法 - 使用与检查工具完全相同的尺寸估计方法
    checkAndAddImage(fileName, pkgPath, foundImages, baseDir, callPath) {
        if (!fileName) return;
        
        const imagePath = this.resolveImagePath(fileName, pkgPath, baseDir);
        
        if (!imagePath) {
            return;
        }
        
        if (foundImages.has(imagePath)) {
            return;
        }
        
        try {
            const dimensions = this.estimateImageDimensions(imagePath);
            if (dimensions) {
                if (dimensions.width > this.maxDimension || dimensions.height > this.maxDimension) {
                    const fileStats = fs.statSync(imagePath);
                    const relativePath = path.relative(this.assetsPath, imagePath);
                    
                    const imageInfo = {
                        path: imagePath,
                        relativePath: relativePath,
                        package: path.relative(this.assetsPath, pkgPath),
                        originalWidth: dimensions.width,
                        originalHeight: dimensions.height,
                        originalSize: fileStats.size,
                        callPath: [...callPath]
                    };
                    
                    // 计算新的尺寸
                    const newDimensions = this.calculateNewDimensions(dimensions.width, dimensions.height);
                    imageInfo.newWidth = newDimensions.width;
                    imageInfo.newHeight = newDimensions.height;
                    imageInfo.shrinkPercentage = newDimensions.shrinkPercentage;
                    
                    this.imagesToResize.push(imageInfo);
                    foundImages.add(imagePath);
                    
                    this.log(`发现大图: ${relativePath} (${dimensions.width}x${dimensions.height}) -> 将缩小到 ${newDimensions.width}x${newDimensions.height} (${newDimensions.shrinkPercentage}%)`, 'detail');
                }
            }
        } catch (error) {
            this.log(`检查图片尺寸失败: ${imagePath} - ${error.message}`, 'warning');
        }
    }

    // 从检查工具复用的方法 - 增强图片尺寸估计方法
    estimateImageDimensions(imagePath) {
        if (!fs.existsSync(imagePath)) {
            this.log(`图片文件不存在: ${imagePath}`, 'warning');
            return null;
        }
        
        try {
            const buffer = fs.readFileSync(imagePath);
            
            // 对于PNG文件
            if (imagePath.toLowerCase().endsWith('.png')) {
                if (buffer.readUInt32BE(0) === 0x89504E47) {
                    const width = buffer.readUInt32BE(16);
                    const height = buffer.readUInt32BE(20);
                    return { width, height };
                }
            }
            
            // 对于JPEG文件
            if (imagePath.toLowerCase().endsWith('.jpg') || imagePath.toLowerCase().endsWith('.jpeg')) {
                if (buffer.readUInt16BE(0) === 0xFFD8) {
                    // JPEG文件，需要解析SOF标记
                    let offset = 2;
                    while (offset < buffer.length - 1) {
                        const marker = buffer.readUInt16BE(offset);
                        // SOF0, SOF1, SOF2 等标记
                        if (marker >= 0xFFC0 && marker <= 0xFFCF && marker !== 0xFFC4 && marker !== 0xFFC8) {
                            // 找到SOF标记
                            const height = buffer.readUInt16BE(offset + 5);
                            const width = buffer.readUInt16BE(offset + 7);
                            return { width, height };
                        }
                        const segmentLength = buffer.readUInt16BE(offset + 2);
                        if (segmentLength < 2) break;
                        offset += 2 + segmentLength;
                    }
                }
            }
            
            this.log(`无法识别图片格式或获取尺寸: ${imagePath}`, 'warning');
        } catch (error) {
            this.log(`读取图片文件失败: ${imagePath} - ${error.message}`, 'warning');
        }
        
        return null;
    }

    // 计算新的图片尺寸
    calculateNewDimensions(originalWidth, originalHeight) {
        let shrinkPercentage = this.minShrinkPercentage;
        
        // 首先应用保底缩小
        let newWidth = Math.round(originalWidth * (1 - shrinkPercentage / 100));
        let newHeight = Math.round(originalHeight * (1 - shrinkPercentage / 100));
        
        // 如果缩小后仍然超过最大尺寸，则进一步缩小到最大尺寸
        if (newWidth > this.maxDimension || newHeight > this.maxDimension) {
            const scale = Math.min(this.maxDimension / originalWidth, this.maxDimension / originalHeight);
            newWidth = Math.round(originalWidth * scale);
            newHeight = Math.round(originalHeight * scale);
            shrinkPercentage = Math.round((1 - scale) * 100);
        }
        
        return {
            width: newWidth,
            height: newHeight,
            shrinkPercentage: shrinkPercentage
        };
    }

    // 从检查工具复用的方法 - 解析图片路径
    resolveImagePath(fileName, pkgPath, baseDir) {
        if (fs.existsSync(fileName)) {
            return fileName;
        }
        
        let imagePath = path.join(baseDir, fileName);
        if (fs.existsSync(imagePath)) {
            return imagePath;
        }
        
        imagePath = path.join(pkgPath, fileName);
        if (fs.existsSync(imagePath)) {
            return imagePath;
        }
        
        if (fileName.startsWith('../') || fileName.startsWith('./')) {
            imagePath = path.resolve(baseDir, fileName);
            if (fs.existsSync(imagePath)) {
                return imagePath;
            }
        }
        
        imagePath = path.join(pkgPath, 'image', fileName);
        if (fs.existsSync(imagePath)) {
            return imagePath;
        }
        
        imagePath = path.join(pkgPath, fileName);
        if (fs.existsSync(imagePath)) {
            return imagePath;
        }
        
        return null;
    }

    // 从检查工具复用的方法 - 查找文件
    findFilesDeep(dir, extensions) {
        if (!fs.existsSync(dir)) return [];
        const results = [];
        const items = fs.readdirSync(dir);
        const exts = extensions ? (Array.isArray(extensions) ? extensions : [extensions]) : null;

        items.forEach(item => {
            if (item.startsWith('.') || item === 'Thumbs.db') return;
            const fullPath = path.join(dir, item);
            try {
                const stat = fs.statSync(fullPath);
                if (stat.isDirectory()) {
                    results.push(...this.findFilesDeep(fullPath, exts));
                } else if (exts === null) {
                    results.push(fullPath);
                } else {
                    const ext = path.extname(item).toLowerCase();
                    if (exts.includes(ext)) {
                        results.push(fullPath);
                    }
                }
            } catch (error) {
                // 忽略错误
            }
        });
        return results;
    }

    // 1. 查找所有已导出组件中的大图
    async findOversizedImagesInExportedComponents() {
        this.log('1. 查找已导出组件中的大图...');
        
        const packages = this.getPackages();
        
        if (packages.length === 0) {
            this.log('未找到任何包', 'error');
            return;
        }

        this.log(`将处理 ${packages.length} 个包: ${packages.join(', ')}`);
        
        const foundImages = new Set();
        const processedComponents = new Set();
        
        // 首先分析所有包的资源ID映射
        this.log('分析包资源ID映射...', 'detail');
        packages.forEach(pkg => {
            this.analyzePackageResourceIds(pkg);
        });

        for (const pkg of packages) {
            this.log(`处理包: ${pkg}`, 'detail');
            const pkgPath = path.join(this.assetsPath, pkg);
            const packageXMLPath = path.join(pkgPath, 'package.xml');
            
            if (!fs.existsSync(packageXMLPath)) {
                this.log(`包 "${pkg}" 没有 package.xml 文件`, 'warning');
                continue;
            }
            
            try {
                const packageContent = fs.readFileSync(packageXMLPath, 'utf8');
                const exportedComponents = this.findExportedComponentsInPackageXML(packageContent);
                
                this.log(`包 "${pkg}" 有 ${exportedComponents.length} 个导出组件`, 'detail');
                
                if (exportedComponents.length === 0) {
                    this.log(`包 "${pkg}" 没有找到导出组件`, 'warning');
                    continue;
                }
                
                for (const componentId of exportedComponents) {
                    const componentFile = this.findComponentFileById(pkgPath, componentId);
                    if (componentFile && !processedComponents.has(componentFile)) {
                        processedComponents.add(componentFile);
                        const callPath = [path.relative(pkgPath, componentFile)];
                        this.findImagesInExportedComponent(componentFile, pkgPath, foundImages, processedComponents, callPath);
                    }
                }
            } catch (error) {
                this.log(`处理包 "${pkg}" 时出错: ${error.message}`, 'error');
            }
        }
        
        this.log(`找到 ${this.imagesToResize.length} 张需要缩小的图片`, 'success');
        return this.imagesToResize;
    }

    // 2. 备份原始图片
    async backupImages() {
        this.log('\n2. 备份原始图片...');
        
        for (const imageInfo of this.imagesToResize) {
            try {
                const backupPath = path.join(this.backupDir, imageInfo.relativePath);
                const backupDir = path.dirname(backupPath);
                
                if (!fs.existsSync(backupDir)) {
                    fs.mkdirSync(backupDir, { recursive: true });
                }
                
                fs.copyFileSync(imageInfo.path, backupPath);
                this.log(`备份: ${imageInfo.relativePath}`, 'detail');
            } catch (error) {
                this.log(`备份失败: ${imageInfo.relativePath} - ${error.message}`, 'error');
            }
        }
        
        this.log(`备份完成，共备份 ${this.imagesToResize.length} 张图片`, 'success');
    }

    // 添加方法：检查文件是否可写
    isFileWritable(filePath) {
        try {
            // 尝试以追加模式打开文件，如果成功则文件可写
            const fd = fs.openSync(filePath, 'a');
            fs.closeSync(fd);
            return true;
        } catch (error) {
            return false;
        }
    }

    // 3. 执行图片缩小
    async resizeImages() {
        this.log('\n3. 执行图片缩小...');
        
        let successCount = 0;
        let failCount = 0;
        let skipCount = 0;
        
        for (const imageInfo of this.imagesToResize) {
            try {
                // 检查文件是否可写
                if (!this.isFileWritable(imageInfo.path)) {
                    this.log(`文件被锁定，跳过: ${imageInfo.relativePath}`, 'warning');
                    this.log(`提示: 请关闭可能占用此文件的程序（如Photoshop、图片查看器等），然后手动重试`, 'warning');
                    skipCount++;
                    continue;
                }
                
                const result = await this.resizeSingleImage(imageInfo);
                if (result) {
                    successCount++;
                    this.resizedImages.push(result);
                } else {
                    failCount++;
                }
            } catch (error) {
                this.log(`缩小图片失败: ${imageInfo.relativePath} - ${error.message}`, 'error');
                failCount++;
            }
        }
        
        this.log(`图片缩小完成: 成功 ${successCount} 张, 失败 ${failCount} 张, 跳过 ${skipCount} 张`, 'success');
        return { successCount, failCount, skipCount };
    }

    // 缩小单张图片
    // 优化 resizeSingleImage 方法中的文件替换逻辑
    async resizeSingleImage(imageInfo) {
        let tempFilePath;
        try {
            const originalStats = fs.statSync(imageInfo.path);
            
            // 统一的临时文件路径
            const tempFileName = 'temp_' + Date.now() + '_' + path.basename(imageInfo.path);
            tempFilePath = path.join(path.dirname(imageInfo.path), tempFileName);
            
            // 使用sharp进行图片缩小，直接输出到临时文件
            await sharp(imageInfo.path)
                .resize(imageInfo.newWidth, imageInfo.newHeight, {
                    fit: 'inside',
                    withoutEnlargement: true
                })
                .toFile(tempFilePath);
            
            // 检查临时文件是否成功创建
            if (!fs.existsSync(tempFilePath)) {
                throw new Error('临时文件创建失败');
            }
            
            const tempStats = fs.statSync(tempFilePath);
            if (tempStats.size === 0) {
                throw new Error('临时文件为空');
            }
            
            // 备份原文件（如果还没有备份的话）
            const backupPath = path.join(this.backupDir, imageInfo.relativePath);
            const backupDir = path.dirname(backupPath);
            
            if (!fs.existsSync(backupDir)) {
                fs.mkdirSync(backupDir, { recursive: true });
            }
            
            if (!fs.existsSync(backupPath)) {
                fs.copyFileSync(imageInfo.path, backupPath);
            }
            
            // 尝试替换原文件 - 使用更安全的方法
            let retryCount = 0;
            const maxRetries = 5;
            let success = false;
            
            while (retryCount < maxRetries && !success) {
                try {
                    // 方法1: 先尝试重命名（原子操作）
                    try {
                        fs.renameSync(tempFilePath, imageInfo.path);
                        success = true;
                        this.log(`使用重命名方式替换文件成功: ${imageInfo.relativePath}`, 'detail');
                    } catch (renameError) {
                        // 如果重命名失败，尝试复制方式
                        this.log(`重命名失败，尝试复制方式: ${imageInfo.relativePath}`, 'detail');
                        fs.copyFileSync(tempFilePath, imageInfo.path);
                        success = true;
                        this.log(`使用复制方式替换文件成功: ${imageInfo.relativePath}`, 'detail');
                    }
                    
                    // 如果成功，删除临时文件
                    if (success && fs.existsSync(tempFilePath)) {
                        fs.unlinkSync(tempFilePath);
                    }
                    
                } catch (error) {
                    retryCount++;
                    this.log(`文件替换失败，重试 ${retryCount}/${maxRetries}: ${imageInfo.relativePath} - ${error.message}`, 'warning');
                    
                    if (retryCount >= maxRetries) {
                        throw new Error(`文件替换失败，临时文件保存在: ${tempFilePath}`);
                    }
                    
                    // 等待一段时间后重试，逐渐增加等待时间
                    const waitTime = 1000 * retryCount;
                    await new Promise(resolve => setTimeout(resolve, waitTime));
                }
            }
            
            if (!success) {
                throw new Error(`经过 ${maxRetries} 次重试后文件替换仍然失败`);
            }
            
            // 验证新文件
            if (!fs.existsSync(imageInfo.path)) {
                throw new Error('新文件不存在');
            }
            
            const newStats = fs.statSync(imageInfo.path);
            if (newStats.size === 0) {
                throw new Error('新文件为空');
            }
            
            const sizeReduction = Math.round((1 - newStats.size / imageInfo.originalSize) * 100);
            
            const result = {
                ...imageInfo,
                newSize: newStats.size,
                sizeReduction: sizeReduction
            };
            
            this.log(`缩小成功: ${imageInfo.relativePath} (${imageInfo.originalWidth}x${imageInfo.originalHeight} -> ${imageInfo.newWidth}x${imageInfo.newHeight}, 文件大小减少 ${sizeReduction}%)`, 'success');
            
            return result;
            
        } catch (error) {
            // 记录临时文件路径，方便用户手动处理
            if (tempFilePath && fs.existsSync(tempFilePath)) {
                this.log(`临时文件已保存: ${tempFilePath}`, 'detail');
                this.log(`手动处理建议: 关闭占用文件的程序后，将临时文件重命名为原文件`, 'detail');
            }
            
            this.log(`缩小失败: ${imageInfo.relativePath} - ${error.message}`, 'error');
            return null;
        }
    }

    // 添加方法：清理旧的临时文件
    cleanupOldTempFiles() {
        this.log('清理旧的临时文件...', 'detail');
        const packages = this.getPackages();
        
        let cleanedCount = 0;
        packages.forEach(pkg => {
            const pkgPath = path.join(this.assetsPath, pkg);
            const allFiles = this.findFilesDeep(pkgPath, null);
            
            allFiles.forEach(file => {
                const fileName = path.basename(file);
                // 清理两种格式的临时文件
                if (fileName.startsWith('temp_') || fileName.includes('.tmp_')) {
                    try {
                        fs.unlinkSync(file);
                        cleanedCount++;
                        this.log(`清理临时文件: ${path.relative(this.assetsPath, file)}`, 'detail');
                    } catch (error) {
                        // 忽略删除失败的文件
                    }
                }
            });
        });
        
        if (cleanedCount > 0) {
            this.log(`清理了 ${cleanedCount} 个旧的临时文件`, 'success');
        }
    }

    // 4. 调整FGUI组件属性
    async adjustFGUIComponentProperties() {
        this.log('\n4. 调整FGUI组件属性...');
        
        let adjustedFiles = new Set();
        let successCount = 0;
        let failCount = 0;

        for (const imageInfo of this.resizedImages) {
            try {
                // 为每个图片添加更多信息，用于loader匹配
                const imageFileName = path.basename(imageInfo.path);
                const imageName = path.basename(imageInfo.path, path.extname(imageInfo.path));
                const enhancedImageInfo = {
                    ...imageInfo,
                    fileName: imageFileName,
                    imageName: imageName
                };
                
                const result = await this.adjustSingleImageFGUIProperties(enhancedImageInfo);
                if (result) {
                    result.adjustedFiles.forEach(file => adjustedFiles.add(file));
                    successCount++;
                } else {
                    failCount++;
                }
            } catch (error) {
                this.log(`调整FGUI属性失败: ${imageInfo.relativePath} - ${error.message}`, 'error');
                failCount++;
            }
        }

        this.log(`FGUI属性调整完成: 成功 ${successCount} 个图片引用, 失败 ${failCount} 个, 修改了 ${adjustedFiles.size} 个XML文件`, 'success');
        return { successCount, failCount, adjustedFiles: Array.from(adjustedFiles) };
    }

    // 调整单个图片对应的FGUI属性
    async adjustSingleImageFGUIProperties(imageInfo) {
        const adjustedFiles = new Set();
        const imageFileName = path.basename(imageInfo.path);
        
        this.log(`调整图片属性: ${imageFileName}`, 'detail');

        // 在包目录中查找所有引用该图片的XML文件
        const pkgPath = path.join(this.assetsPath, imageInfo.package);
        const xmlFiles = this.findFilesDeep(pkgPath, '.xml');
        
        let totalAdjustments = 0;
        
        for (const xmlFile of xmlFiles) {
            try {
                let content = fs.readFileSync(xmlFile, 'utf8');
                let modified = false;
                
                // 查找引用该图片的组件
                const imageRefs = this.findImageReferencesInXML(content, imageInfo);
                
                for (const ref of imageRefs) {
                    const adjustedContent = this.adjustComponentProperties(content, ref, imageInfo);
                    if (adjustedContent !== content) {
                        content = adjustedContent;
                        modified = true;
                        totalAdjustments++;
                        this.log(`  调整: ${path.relative(pkgPath, xmlFile)} - ${ref.type} "${ref.name || ref.id}"`, 'detail');
                    }
                }
                
                if (modified) {
                    // 检查是否已经有备份文件，如果没有才创建备份
                    // const backupPath = xmlFile + '.backup';
                    // if (!fs.existsSync(backupPath)) {
                    //     fs.copyFileSync(xmlFile, backupPath);
                    //     this.log(`  创建备份: ${path.relative(pkgPath, xmlFile)}.backup`, 'detail');
                    // }
                    
                    // 写入修改后的内容
                    fs.writeFileSync(xmlFile, content, 'utf8');
                    adjustedFiles.add(path.relative(this.assetsPath, xmlFile));
                }
                
            } catch (error) {
                this.log(`处理XML文件失败: ${xmlFile} - ${error.message}`, 'warning');
            }
        }
        
        if (totalAdjustments > 0) {
            this.log(`图片 ${imageFileName} 调整了 ${totalAdjustments} 个组件引用`, 'success');
            return { adjustedFiles, totalAdjustments };
        } else {
            this.log(`未找到图片 ${imageFileName} 的引用`, 'warning');
            return null;
        }
    }

    // 在XML内容中查找图片引用
    findImageReferencesInXML(xmlContent, imageInfo) {
        const refs = [];
        const imageFileName = imageInfo.fileName;
        const imageName = imageInfo.imageName;
        
        // 查找直接的文件名引用
        const fileNameRegex = new RegExp(`<image[^>]*?fileName="[^"]*${this.escapeRegExp(imageFileName)}"[^>]*>`, 'gi');
        let match;
        
        while ((match = fileNameRegex.exec(xmlContent)) !== null) {
            const fullTag = match[0];
            
            // 解析标签属性
            const attributes = this.parseXMLAttributes(fullTag);
            refs.push({
                type: 'image',
                name: attributes.name,
                id: attributes.id,
                fullTag: fullTag,
                start: match.index,
                end: match.index + fullTag.length - 1,
                attributes: attributes
            });
        }

        // 查找loader引用 - 通过资源ID匹配
        const loaderRegex = /<loader[^>]*>/gi;
        while ((match = loaderRegex.exec(xmlContent)) !== null) {
            const fullTag = match[0];
            const attributes = this.parseXMLAttributes(fullTag);
            
            // 检查loader是否引用了该图片
            let matchesImage = false;
            
            // 通过ui://URL匹配
            if (attributes.url && attributes.url.startsWith('ui://')) {
                const packageId = this.packageIds.get(imageInfo.package);
                if (packageId) {
                    const expectedUrl = `ui://${packageId}${this.findResourceIdByImagePath(imageInfo.path, imageInfo.package)}`;
                    if (attributes.url === expectedUrl) {
                        matchesImage = true;
                    }
                }
            }
            
            // 通过文件名匹配（备用方案）
            if (!matchesImage && attributes.url && attributes.url.includes(imageName)) {
                matchesImage = true;
            }
            
            // 如果有autoSize属性且匹配图片，添加到处理列表
            if (matchesImage && attributes.autoSize) {
                refs.push({
                    type: 'loader',
                    name: attributes.name,
                    id: attributes.id,
                    fullTag: fullTag,
                    start: match.index,
                    end: match.index + fullTag.length - 1,
                    attributes: attributes
                });
            }
        }
        
        return refs;
    }

    // 根据图片路径查找资源ID
    findResourceIdByImagePath(imagePath, pkg) {
        const resources = this.packageResources.get(pkg) || [];
        
        for (const resource of resources) {
            if (resource.type === 'resource') {
                // 检查资源是否对应这个图片文件
                const pkgPath = path.join(this.assetsPath, pkg);
                const possiblePaths = [
                    path.join(pkgPath, 'image', resource.name),
                    path.join(pkgPath, 'image', resource.name + '.png'),
                    path.join(pkgPath, 'image', resource.name + '.jpg'),
                    path.join(pkgPath, 'image', resource.name + '.jpeg'),
                    path.join(pkgPath, resource.name),
                    path.join(pkgPath, resource.name + '.png'),
                    path.join(pkgPath, resource.name + '.jpg'),
                    path.join(pkgPath, resource.name + '.jpeg')
                ];
                
                for (const possiblePath of possiblePaths) {
                    if (possiblePath === imagePath) {
                        return resource.id;
                    }
                }
            }
        }
        
        return null;
    }

    // 调整组件属性
    adjustComponentProperties(xmlContent, ref, imageInfo) {
        if (!ref || !ref.fullTag) {
            this.log(`错误：引用对象无效`, 'error');
            return xmlContent;
        }
        
        const { fullTag, start, end, attributes, type } = ref;
        
        let newTag = fullTag;
        let modified = false;
        
        if (type === 'image') {
            // 对于image组件，确保有size属性（取消原大小设置）
            // 使用图片的原始尺寸作为size属性
            const originalSize = `${imageInfo.originalWidth},${imageInfo.originalHeight}`;
            
            // 检查是否已经有size属性
            if (attributes.size) {
                // 如果已经有size属性，更新它
                const oldSize = attributes.size;
                if (oldSize !== originalSize) {
                    newTag = newTag.replace(`size="${oldSize}"`, `size="${originalSize}"`);
                    this.log(`    更新size属性: ${oldSize} -> ${originalSize}`, 'detail');
                    modified = true;
                }
            } else {
                // 如果没有size属性，添加它
                // 注意：需要在标签结束前添加属性
                if (newTag.endsWith('/>')) {
                    // 自闭合标签：<image ... />
                    newTag = newTag.replace('/>', ` size="${originalSize}"/>`);
                } else {
                    // 普通标签：<image ... >
                    newTag = newTag.replace('>', ` size="${originalSize}">`);
                }
                this.log(`    添加size属性: ${originalSize}（取消原大小设置）`, 'detail');
                modified = true;
            }
        } else if (type === 'loader') {
            // 对于loader组件，移除autoSize属性，添加fill="scale"属性
            let loaderModified = false;
            
            // 移除autoSize属性
            if (attributes.autoSize) {
                newTag = newTag.replace(/\s+autoSize="[^"]*"/, '');
                this.log(`    移除autoSize属性: ${attributes.autoSize}`, 'detail');
                loaderModified = true;
            }
            
            // 添加fill="scale"属性
            if (!attributes.fill) {
                if (newTag.endsWith('/>')) {
                    newTag = newTag.replace('/>', ` fill="scale"/>`);
                } else {
                    newTag = newTag.replace('>', ` fill="scale">`);
                }
                this.log(`    添加fill="scale"属性`, 'detail');
                loaderModified = true;
            } else if (attributes.fill !== 'scale') {
                newTag = newTag.replace(`fill="${attributes.fill}"`, 'fill="scale"');
                this.log(`    修改fill属性为scale`, 'detail');
                loaderModified = true;
            }
            
            modified = loaderModified;
        }
        
        // 如果标签被修改了，替换原内容
        if (modified && newTag) {
            return xmlContent.substring(0, start) + newTag + xmlContent.substring(end + 1);
        }
        
        return xmlContent;
    }

    // 工具方法：转义正则表达式特殊字符
    escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }

    // 工具方法：查找标签开始位置
    findTagStart(content, position) {
        let start = position;
        while (start > 0 && content[start] !== '<') {
            start--;
        }
        return start;
    }

    // 工具方法：查找标签结束位置
    findTagEnd(content, position) {
        let end = position;
        while (end < content.length && content[end] !== '>') {
            end++;
        }
        return end;
    }

    // 工具方法：解析XML属性
    parseXMLAttributes(tag) {
        const attributes = {};
        const attrRegex = /(\w+)\s*=\s*"([^"]*)"/g;
        let match;
        
        while ((match = attrRegex.exec(tag)) !== null) {
            attributes[match[1]] = match[2];
        }
        
        return attributes;
    }

    // 5. 生成报告
    generateReport() {
        this.log('\n5. 生成处理报告...');
        
        const reportContent = [];
        
        reportContent.push('='.repeat(70));
        reportContent.push('        USS FGUI 图片缩小工具 - 处理报告');
        reportContent.push('='.repeat(70));
        reportContent.push(`处理时间: ${new Date().toLocaleString()}`);
        reportContent.push(`项目路径: ${this.fguiProjectPath}`);
        if (this.targetPackage) {
            reportContent.push(`目标包: ${this.targetPackage}`);
        } else {
            reportContent.push(`目标包: 所有包`);
        }
        reportContent.push(`备份目录: ${this.backupDir}`);
        reportContent.push(`日志文件: ${this.logFile}`);
        reportContent.push(`配置: 保底缩小 ${this.minShrinkPercentage}%, 最大边长 ${this.maxDimension}px`);
        reportContent.push('');
        
        // 处理统计
        reportContent.push('📊 处理统计:');
        reportContent.push(`   发现大图: ${this.imagesToResize.length} 张`);
        reportContent.push(`   成功缩小: ${this.resizedImages.length} 张`);
        reportContent.push(`   处理失败: ${this.imagesToResize.length - this.resizedImages.length} 张`);
        reportContent.push('');
        
        // 按包分组显示处理结果
        const imagesByPackage = {};
        this.resizedImages.forEach(img => {
            if (!imagesByPackage[img.package]) {
                imagesByPackage[img.package] = [];
            }
            imagesByPackage[img.package].push(img);
        });
        
        reportContent.push('🖼️ 处理详情 (按包分组):');
        Object.keys(imagesByPackage).forEach(pkg => {
            reportContent.push(`   包 "${pkg}" (${imagesByPackage[pkg].length}张):`);
            imagesByPackage[pkg].forEach(img => {
                const sizeInfo = `尺寸: ${img.originalWidth}x${img.originalHeight} -> ${img.newWidth}x${img.newHeight}`;
                const sizeReduction = `大小: ${this.formatFileSize(img.originalSize)} -> ${this.formatFileSize(img.newSize)} (减少${img.sizeReduction}%)`;
                reportContent.push(`     ${img.relativePath}`);
                reportContent.push(`         ${sizeInfo}, ${sizeReduction}`);
            });
        });
        reportContent.push('');
        
        // 节省空间统计
        if (this.resizedImages.length > 0) {
            const totalOriginalSize = this.resizedImages.reduce((sum, img) => sum + img.originalSize, 0);
            const totalNewSize = this.resizedImages.reduce((sum, img) => sum + img.newSize, 0);
            const totalReduction = Math.round((1 - totalNewSize / totalOriginalSize) * 100);
            
            reportContent.push('💾 空间节省统计:');
            reportContent.push(`   原始总大小: ${this.formatFileSize(totalOriginalSize)}`);
            reportContent.push(`   缩小后大小: ${this.formatFileSize(totalNewSize)}`);
            reportContent.push(`   总共节省: ${this.formatFileSize(totalOriginalSize - totalNewSize)} (${totalReduction}%)`);
            reportContent.push('');
        }
        
        // 策略说明
        reportContent.push('🎯 处理策略:');
        reportContent.push('   ✅ 图片文件已按比例缩小');
        reportContent.push('   ✅ 为image组件添加size属性（取消原大小设置）');
        reportContent.push('   ✅ 为loader组件移除autoSize属性');
        reportContent.push('   ✅ 为loader组件添加fill="scale"属性');
        reportContent.push('   ✅ FGUI会自动拉伸图片以适应组件尺寸');
        reportContent.push('');
        
        // 重要提示
        reportContent.push('💡 重要提示:');
        reportContent.push('   1. 图片文件已被缩小，但FGUI界面尺寸保持不变');
        reportContent.push('   2. 已为image组件添加size属性，确保图片拉伸到组件尺寸');
        reportContent.push('   3. 已为loader组件配置fill="scale"，确保图片按比例填充');
        reportContent.push('   4. 原始图片和XML文件已备份');
        reportContent.push('   5. 如需恢复，可从备份目录复制文件覆盖');
        reportContent.push('');
        
        // 总结
        reportContent.push('='.repeat(70));
        if (this.resizedImages.length === this.imagesToResize.length) {
            reportContent.push('✅ 所有图片处理完成！FGUI组件已正确配置');
        } else if (this.resizedImages.length > 0) {
            reportContent.push('⚠️  部分图片处理完成，有失败情况');
        } else {
            reportContent.push('❌ 图片处理失败');
        }
        reportContent.push('='.repeat(70));
        
        // 输出到控制台和日志
        reportContent.forEach(line => {
            if (line.includes('❌')) {
                this.log(line.replace('❌ ', ''), 'error');
            } else if (line.includes('⚠️')) {
                this.log(line.replace('⚠️ ', ''), 'warning');
            } else if (line.includes('✅')) {
                this.log(line.replace('✅ ', ''), 'success');
            } else if (line.startsWith('=')) {
                console.log(line);
            } else if (line.trim()) {
                console.log(line);
            }
        });
        
        const fullReport = reportContent.join('\n');
        fs.appendFileSync(this.logFile, '\n' + fullReport + '\n', 'utf8');
        
        return {
            totalFound: this.imagesToResize.length,
            totalResized: this.resizedImages.length,
            backupDir: this.backupDir,
            logFile: this.logFile
        };
    }

    // 格式化文件大小
    formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    // 6. 用户确认执行
    async promptUserConfirmation() {
        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });

        return new Promise((resolve) => {
            console.log('\n' + '='.repeat(50));
            console.log('⚠️  确认执行图片缩小操作');
            console.log('='.repeat(50));
            console.log(`将处理 ${this.imagesToResize.length} 张图片:`);
            
            // 按包分组显示预览
            const imagesByPackage = {};
            this.imagesToResize.forEach(img => {
                if (!imagesByPackage[img.package]) {
                    imagesByPackage[img.package] = [];
                }
                imagesByPackage[img.package].push(img);
            });
            
            Object.keys(imagesByPackage).forEach(pkg => {
                console.log(`\n  包 "${pkg}" (${imagesByPackage[pkg].length}张):`);
                imagesByPackage[pkg].slice(0, 5).forEach((img, index) => {
                    console.log(`    ${index + 1}. ${img.relativePath} (${img.originalWidth}x${img.originalHeight} -> ${img.newWidth}x${img.newHeight})`);
                });
                if (imagesByPackage[pkg].length > 5) {
                    console.log(`    ... 还有 ${imagesByPackage[pkg].length - 5} 张图片`);
                }
            });
            
            console.log('\n💡 重要说明:');
            console.log('   - 图片文件将被缩小，但FGUI组件尺寸保持不变');
            console.log('   - 将为image组件添加size属性（取消原大小设置）');
            console.log('   - 将为loader组件移除autoSize属性并添加fill="scale"');
            console.log('   - 原始图片和XML文件将备份');
            console.log('\n请输入 "YES" 确认执行，或输入其他内容取消:');
            
            rl.question('', (answer) => {
                rl.close();
                resolve(answer.trim().toUpperCase() === 'YES');
            });
        });
    }

    // 主运行函数
    async run() {
        this.log('🚀 开始 USS FGUI 图片缩小工具 (增强版)...');
        this.log(`开始时间: ${new Date().toLocaleString()}`);
        
        try {
            // 清理旧的临时文件
            this.cleanupOldTempFiles();

            // 如果没有通过命令行指定包，显示包选择菜单
            if (!this.targetPackage) {
                this.targetPackage = await this.showPackageSelection();
                if (this.targetPackage === null) {
                    this.log('将处理所有包', 'info');
                } else if (this.targetPackage === undefined) {
                    this.log('❌ 用户取消选择');
                    process.exit(0);
                } else {
                    this.log(`已选择包: ${this.targetPackage}`, 'info');
                }
            }
            
            // 1. 查找需要缩小的图片
            await this.findOversizedImagesInExportedComponents();
            
            if (this.imagesToResize.length === 0) {
                this.log('🎉 未找到需要缩小的图片，任务完成！');
                process.exit(0);
            }
            
            // 2. 用户确认
            const confirmed = await this.promptUserConfirmation();
            if (!confirmed) {
                this.log('❌ 用户取消操作');
                process.exit(0);
            }
            
            // 3. 备份图片
            await this.backupImages();
            
            // 4. 执行缩小
            await this.resizeImages();
            
            // 5. 调整FGUI组件属性
            if (this.resizedImages.length > 0) {
                await this.adjustFGUIComponentProperties();
            }
            
            // 6. 生成报告
            const result = this.generateReport();
            
            this.log(`完成时间: ${new Date().toLocaleString()}`);
            this.log(`详细报告已保存: ${result.logFile}`);
            
        } catch (error) {
            this.log(`工具运行失败: ${error.message}`, 'error');
            process.exit(1);
        }
    }
}

// 运行工具
if (require.main === module) {
    // 检查是否安装了sharp
    try {
        require.resolve('sharp');
    } catch (e) {
        console.error('❌ 错误: 需要安装 sharp 库');
        console.log('请运行: npm install sharp');
        process.exit(1);
    }

    // 解析命令行参数
    const args = process.argv.slice(2);
    let targetPackage = null;
    
    for (let i = 0; i < args.length; i++) {
        if (args[i] === '--package' && i + 1 < args.length) {
            targetPackage = args[i + 1];
            break;
        }
    }
    
    const resizer = new USSImageResizerEnhanced(targetPackage);
    resizer.run();
}

module.exports = USSImageResizerEnhanced;